﻿using UnityEngine;
using System.IO;
using Devil;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace GameToolkit
{
    public enum LogCat
    {
        Editor = 1,
        Game = 2,
        Asset = 4,
        Table = 8,

        Network = 0x10,
        AI = 0x20,
        Persistent = 0x40,
        Native = 0x80,
        UI = 0x100,
        
        Task = 0x200,
        Event = 0x400,
        Detect = 0x800,
        MSG = 0x1000,
    }

    // 打印日志
    public class RTLog
    {
        static LogCat s_Categories = (LogCat)(-1);
        static string s_LogFolder = "";
        static string s_BackupFolder = "";
        public static string BackupFolder { get { return s_BackupFolder; } }

        public static string GetProjectBackFolder()
        {
            if (string.IsNullOrEmpty(s_BackupFolder))
                return null;
            var data = NativeFileSystem.GetFolderName(ParallelUnity.dataPath);
            return Path.Combine(s_BackupFolder, NativeFileSystem.GetFileName(data, false));
        }

        public static string CreateBackupFilePath(string relativeFolder, string file)
        {
            if (string.IsNullOrEmpty(s_BackupFolder) || !File.Exists(file))
                return null;
            var fname = NativeFileSystem.GetFileName(file, false);
            var t = File.GetLastWriteTime(file);
            var data = NativeFileSystem.GetFolderName(ParallelUnity.dataPath);
            var path = Path.Combine(s_BackupFolder, NativeFileSystem.GetFileName(data, false), relativeFolder, ParallelUtils.Concat(fname, t.ToString("yyMMddHHmmss")));
            return path;
        }

        public static bool UseCategory(LogCat cat)
        {
            return (s_Categories & cat) != 0;
        }

        static string Format(LogCat cat, string content)
        {
            return ParallelUtils.Concat("[", cat.ToString(), "] ", content);
        }

        static string Format(LogCat cat, string format, params object[] args)
        {
            return ParallelUtils.Concat("[", cat.ToString(), "] ", string.Format(format, args));
        }

        public static void Log(LogCat cat, string content)
        {
//#if UNITY_EDITOR
//            WriteLog("I", cat, content);
//#endif
            if (UseCategory(cat))
                Debug.Log(Format(cat, content));
        }

        public static void Log(LogCat cat, UnityEngine.Object context, string content)
        {
//#if UNITY_EDITOR
//            WriteLog("I", cat, content);
//#endif
            if (UseCategory(cat))
                Debug.Log(Format(cat, content), context);
        }

        public static void LogFormat(LogCat cat, string format, params object[] args)
        {
//#if UNITY_EDITOR
//            WriteLog("I", cat, string.Format(format, args));
//#endif
            if (UseCategory(cat))
                Debug.Log(Format(cat, format, args));
        }

        public static void LogFormat(LogCat cat, UnityEngine.Object context, string format, params object[] args)
        {
//#if UNITY_EDITOR
//            WriteLog("I", cat, string.Format(format, args));
//#endif
            if (UseCategory(cat))
                Debug.Log(Format(cat, format, args), context);
        }

        public static void LogWarning(LogCat cat, string content)
        {
//#if UNITY_EDITOR
//            WriteLog("W", cat, content);
//#endif
            if (UseCategory(cat))
                Debug.LogWarning(Format(cat, content));
        }

        public static void LogWarning(LogCat cat, UnityEngine.Object context, string content)
        {
//#if UNITY_EDITOR
//            WriteLog("W", cat, content);
//#endif
            if (UseCategory(cat))
                Debug.LogWarning(Format(cat, content), context);
        }

        public static void LogWarningFormat(LogCat cat, string format, params object[] args)
        {
//#if UNITY_EDITOR
//            WriteLog("W", cat, string.Format(format, args));
//#endif
            if (UseCategory(cat))
                Debug.LogWarning(Format(cat, format, args));
        }

        public static void LogWarningFormat(LogCat cat, UnityEngine.Object context, string format, params object[] args)
        {
//#if UNITY_EDITOR
//            WriteLog("W", cat, string.Format(format, args));
//#endif
            if (UseCategory(cat))
                Debug.LogWarning(Format(cat, format, args), context);
        }

        public static void LogError(LogCat cat, string content)
        {
            //#if UNITY_EDITOR
            //            WriteLog("E", cat, content);
            //#endif
            //if (UseCategory(cat))
                Debug.LogError(Format(cat, content));
        }

        public static void LogError(LogCat cat, UnityEngine.Object context, string content)
        {
            //#if UNITY_EDITOR
            //            WriteLog("E", cat, content);
            //#endif
            //if (UseCategory(cat))
                Debug.LogError(Format(cat, content), context);
        }

        public static void LogErrorFormat(LogCat cat, string format, params object[] args)
        {
            //#if UNITY_EDITOR
            //            WriteLog("E", cat, string.Format(format, args));
            //#endif
            //if (UseCategory(cat))
                Debug.LogError(Format(cat, format, args));
        }

        public static void LogErrorFormat(LogCat cat, UnityEngine.Object context, string format, params object[] args)
        {
            //#if UNITY_EDITOR
            //            WriteLog("E", cat, string.Format(format, args));
            //#endif
            //if (UseCategory(cat))
                Debug.LogError(Format(cat, format, args), context);
        }

#if UNITY_EDITOR
        //const string stackAt = "RTLog.cs:line ";
        static bool sPlaying;

        [InitializeOnLoadMethod]
        static void InitWriter()
        {
            //EditorApplication.playModeStateChanged += OnPlayStateChanged;
            s_Categories = (LogCat)EditorPrefs.GetInt("RTLogCat", -1);
            s_LogFolder = EditorPrefs.GetString("RTLogFolder", "");
            s_BackupFolder = EditorPrefs.GetString("BackupFolder", "");
        }

        //private static void OnPlayStateChanged(PlayModeStateChange obj)
        //{
        //    if (obj == PlayModeStateChange.EnteredPlayMode)
        //    {
        //        sPlaying = true;
        //        if (sLogWriter != null)
        //            sLogWriter.StopWrite();
        //        if (!string.IsNullOrEmpty(s_LogFolder))
        //        {
        //            sLogWriter = new LogWriter(Application.dataPath + "/../logs");
        //            sLogWriter.StartWrite();
        //        }
        //        Application.logMessageReceived += HandleLog;
        //    }
        //    else
        //    {
        //        sPlaying = false;
        //        Application.logMessageReceived -= HandleLog;
        //        if (sLogWriter != null)
        //        {
        //            sLogWriter.StopWrite();
        //            sLogWriter = null;
        //        }
        //    }
        //}

        //static void HandleLog(string condition, string stackTrace, LogType type)
        //{
        //    if (sLogWriter != null)
        //    {
        //        sLogWriter.Append(type, condition, stackTrace);
        //    }
        //}

        [ProjectConfig(Title = "Game Toolkit/RT Logcat"), System.Serializable]
        class RTLogcatConfig : ProjectConfiguration.Configurable
        {
            public override void OnGUI()
            {
                OnPreference();

                base.OnGUI();
            }
        }

//#if UNITY_2019_1_OR_NEWER
//        class DevilPreference : SettingsProvider
//        {
//            public DevilPreference() : base("Devil Framework/RT Logcat", SettingsScope.User) { }

//            public override void OnGUI(string searchContext)
//            {
//                base.OnGUI(searchContext);
//                OnPreference();
//            }
//        }

//        [SettingsProvider]
//        static SettingsProvider Settings()
//        {
//            return new DevilPreference();
//        }
//#else
//        [PreferenceItem("Devil Framework")]
//#endif
        public static void OnPreference()
        {
            var v = (LogCat) EditorGUILayout.EnumFlagsField("Log Cat", s_Categories);
            if(v != s_Categories)
            {
                s_Categories = v;
                EditorPrefs.SetInt("RTLogCat", (int) v);
            }
            if(FolderField("Log Files Output", "RTLogFolder", ref s_LogFolder))
            {
                //if (sLogWriter != null)
                //{
                //    sLogWriter.StopWrite();
                //    sLogWriter = null;
                //}
                //if (sPlaying && !string.IsNullOrEmpty(s_LogFolder))
                //{
                //    sLogWriter = new LogWriter(s_LogFolder);
                //    sLogWriter.StartWrite();
                //}
            }
            FolderField("Backup Folder", "BackupFolder", ref s_BackupFolder);
        }

        static bool FolderField(string prefix, string persistent, ref string folder)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel(prefix);
            var newFolder = EditorGUILayout.TextField(folder);
            if (GUILayout.Button("浏览", GUILayout.Width(40)))
            {
                var f = EditorUtility.OpenFolderPanel(prefix, string.IsNullOrEmpty(newFolder) ? 
                    Application.dataPath : NativeFileSystem.GetFolderName(newFolder),
                    NativeFileSystem.GetFileName(folder, false));
                if (!string.IsNullOrEmpty(f))
                    newFolder = f;
            }
            var dirty = newFolder != folder;
            if (dirty)
            {
                folder = newFolder;
                if (!string.IsNullOrEmpty(persistent))
                    EditorPrefs.SetString(persistent, folder);
            }
            EditorGUILayout.EndHorizontal();
            return dirty;
        }
#endif

    }
}